package com.hopes.bizz.risk.statistic.serivce.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hopes.bizz.common.core.util.DateUtils;
import com.hopes.bizz.risk.common.constant.RiskDicConstant;
import com.hopes.bizz.risk.common.constant.enums.RiskSysDictEnum;
import com.hopes.bizz.risk.control.entity.RiskControlMeasureEntity;
import com.hopes.bizz.risk.control.entity.RiskMeasureTaskRecordEntity;
import com.hopes.bizz.risk.control.entity.RiskOperationalEvaluationEntity;
import com.hopes.bizz.risk.control.entity.RiskUnitEntity;
import com.hopes.bizz.risk.control.mapper.*;
import com.hopes.bizz.risk.statistic.bo.RiskUnitClassifyBO;
import com.hopes.bizz.risk.statistic.serivce.OperationStatisticService;
import com.hopes.bizz.risk.statistic.vo.*;
import com.hopes.boss.admin.api.entity.SysDictItem;
import com.hopes.boss.admin.api.resolver.DictResolver;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yumr
 * @Description 机制运行情况
 * @time 2023/8/1 13:46
 */
@RequiredArgsConstructor
@Service("operationStatisticService")
public class OperationStatisticServiceImpl implements OperationStatisticService {

    private final RiskObjectMapper riskObjectMapper;
    private final RiskUnitMapper riskUnitMapper;
    private final RiskUnitEventMapper riskUnitEventMapper;
    private final RiskControlMeasureMapper riskControlMeasureMapper;
    private final RiskMeasureTaskRecordMapper riskMeasureTaskRecordMapper;
    private final RiskOperationalEvaluationMapper riskOperationalEvaluationMapper;

    @Override
    public RiskCountVO getRiskCount() {
        final RiskCountVO riskCountVO = new RiskCountVO();
        /* 风险对象 */
        final Long riskObjectNum = riskObjectMapper.selectCount(Wrappers.lambdaQuery());
        /* 风险单元 */
        final Long riskUnitNum = riskUnitMapper.selectCount(Wrappers.lambdaQuery());
        /* 风险事件 */
        final Long riskUnitEventNum = riskUnitEventMapper.selectCount(Wrappers.lambdaQuery());
        /* 管控措施 */
        final Long riskControlMeasureNum = riskControlMeasureMapper.selectCount(Wrappers.lambdaQuery());

        riskCountVO.setRiskObjectCount(riskObjectNum);
        riskCountVO.setRiskUnitCount(riskUnitNum);
        riskCountVO.setRiskUnitEventCount(riskUnitEventNum);
        riskCountVO.setRiskControlCount(riskControlMeasureNum);
        return riskCountVO;
    }

    @Override
    public List<RiskIdentifyVO> riskIdentify() {
        final List<RiskIdentifyVO> riskIdentifyVOList = new ArrayList<>();
        /* 查询风险管控措施 */
        final List<RiskControlMeasureEntity> controlMeasureEntityList = riskControlMeasureMapper.selectList(
                Wrappers.<RiskControlMeasureEntity>lambdaQuery().select(RiskControlMeasureEntity::getId, RiskControlMeasureEntity::getRiskUnitId));
        final Map<Long, Long> controlMeasureMap = controlMeasureEntityList.stream().filter(e ->
                ObjectUtil.isNotNull(e.getRiskUnitId())).collect(Collectors.groupingBy(RiskControlMeasureEntity::getRiskUnitId, Collectors.counting()));
        /* 查询风险单元 */
        final List<RiskUnitEntity> riskUnitEntityList = riskUnitMapper.selectList(Wrappers.<RiskUnitEntity>lambdaQuery().select(RiskUnitEntity::getId, RiskUnitEntity::getRiskUnitType));
        final Map<Integer, List<RiskUnitEntity>> groupMap = riskUnitEntityList.parallelStream().filter(e ->
                ObjectUtil.isNotNull(e.getRiskUnitType())).collect(Collectors.groupingBy(RiskUnitEntity::getRiskUnitType));
        groupMap.forEach((k, v) -> {
            final RiskIdentifyVO riskIdentifyVO = new RiskIdentifyVO();
            riskIdentifyVO.setRiskUnitType(k);
            int finishNum = 0;
            int unFinishNum = 0;
            for (RiskUnitEntity item : v) {
                if (!controlMeasureMap.containsKey(item.getId()) || controlMeasureMap.get(item.getId()) == 0) {
                    unFinishNum++;
                } else {
                    finishNum++;
                }
            }
            riskIdentifyVO.setFinishNum(finishNum);
            riskIdentifyVO.setNotFinishNum(unFinishNum);
            riskIdentifyVOList.add(riskIdentifyVO);
        });
        return riskIdentifyVOList;
    }

    @Override
    public List<RiskObjectStatisticVO> listRiskObjectStatisticVO() {
        return riskUnitMapper.listRiskObjectStatisticVO();
    }

    @Override
    public RiskUnitClassifyVO riskUnitClassify() {
        // 1、结果
        final RiskUnitClassifyVO riskUnitClassifyVO = new RiskUnitClassifyVO();
        // 2、字典数据
        final List<SysDictItem> riskLevelList = DictResolver.getItemsByType(RiskSysDictEnum.risk_level);
        final List<SysDictItem> riskUnitTypeList = DictResolver.getItemsByType(RiskSysDictEnum.risk_unit_type);
        riskUnitClassifyVO.setRiskPointTypeLabelValueList(riskUnitTypeList);
        riskUnitClassifyVO.setHazardSourceLevelLabelValueList(riskLevelList);

        // 3、查询风险单元
        final LambdaQueryWrapper<RiskUnitEntity> wrapper = Wrappers.<RiskUnitEntity>lambdaQuery()
                .isNotNull(RiskUnitEntity::getRiskUnitType).isNotNull(RiskUnitEntity::getRiskLevel)
                .select(RiskUnitEntity::getRiskUnitType, RiskUnitEntity::getRiskLevel);
        final List<RiskUnitEntity> riskUnitEntityList = riskUnitMapper.selectList(wrapper);

        // 4、根据风险点类型分组
        final List<RiskUnitClassifyBO> collect = new ArrayList<>();

        final Map<Integer, List<RiskUnitEntity>> collectMapByType = riskUnitEntityList.parallelStream().filter(e -> ObjectUtil.isNotNull(e.getRiskUnitType())).collect(Collectors.groupingBy(RiskUnitEntity::getRiskUnitType));
        collectMapByType.forEach((k, v) -> {
            final Map<Integer, List<RiskUnitEntity>> collectMapByLevel = v.parallelStream().collect(Collectors.groupingBy(RiskUnitEntity::getRiskLevel));
            for (SysDictItem levelItem : riskLevelList) {
                boolean flag = false;
                final RiskUnitClassifyBO riskUnitClassifyBO = new RiskUnitClassifyBO();
                for (Integer level : collectMapByLevel.keySet()) {
                    if (levelItem.getCode().equals(level.toString())) {
                        BeanUtils.copyProperties(collectMapByLevel.get(level).get(0), riskUnitClassifyBO);
                        riskUnitClassifyBO.setNum(collectMapByLevel.get(level).size());
                        collect.add(riskUnitClassifyBO);
                        flag = true;
                    }
                }
                if (!flag) {
                    riskUnitClassifyBO.setRiskLevel(Integer.valueOf(levelItem.getCode()));
                    riskUnitClassifyBO.setRiskUnitType(k);
                    riskUnitClassifyBO.setNum(0);
                    collect.add(riskUnitClassifyBO);
                }
            }
        });
        riskUnitClassifyVO.setCollect(collect.parallelStream().collect(Collectors.groupingBy(RiskUnitClassifyBO::getRiskUnitTypeStr)));
        return riskUnitClassifyVO;
    }

    @Override
    public HiddenCheckResultVO hiddenCheckResult(Integer year) {
        // 结果
        final HiddenCheckResultVO hiddenCheckResultVO = new HiddenCheckResultVO();
        hiddenCheckResultVO.setConform(groupByMonth(null));
        hiddenCheckResultVO.setNotConform(groupByMonth(null));

        // 只统计当年一整年的数据
        Date beginTime = DateUtils.parseDate(year + "-01-01", "yyyy-MM-dd");
        Date endTime = DateUtils.parseDate(year + "-12-31", "yyyy-MM-dd");
        /* 查询时间范围内的隐患排查记录 */
        final LambdaQueryWrapper<RiskMeasureTaskRecordEntity> wrapper = Wrappers.<RiskMeasureTaskRecordEntity>lambdaQuery()
                .ge(RiskMeasureTaskRecordEntity::getTaskStartTime, beginTime)
                .le(RiskMeasureTaskRecordEntity::getTaskStartTime, endTime)
                .eq(RiskMeasureTaskRecordEntity::getTaskStatus, RiskDicConstant.HIDDEN_CHECK_TASK_STATUS_FINISH);
        final List<RiskMeasureTaskRecordEntity> riskMeasureTaskRecordList = riskMeasureTaskRecordMapper.selectList(wrapper);
        if (CollectionUtil.isEmpty(riskMeasureTaskRecordList)) {
            return hiddenCheckResultVO;
        }
        /* 排查结果 Map */
        final Map<Integer, List<RiskMeasureTaskRecordEntity>> listMap = riskMeasureTaskRecordList.stream().filter(e ->
                ObjectUtil.isNotNull(e.getCheckStatus())).collect(Collectors.groupingBy(RiskMeasureTaskRecordEntity::getCheckStatus));

        hiddenCheckResultVO.setConform(groupByMonth(listMap.get(RiskDicConstant.HIDDEN_CHECK_STATUS_CONFORM)));
        hiddenCheckResultVO.setNotConform(groupByMonth(listMap.get(RiskDicConstant.HIDDEN_CHECK_STATUS_NOT_CONFORM)));
        return hiddenCheckResultVO;
    }

    @Override
    public HiddenCheckStatusVO hiddenCheckStatus(Integer year) {
        // 1、结果
        final HiddenCheckStatusVO hiddenCheckStatusVO = new HiddenCheckStatusVO();
        hiddenCheckStatusVO.setExpire(groupByMonth(null));
        hiddenCheckStatusVO.setFinish(groupByMonth(null));
        hiddenCheckStatusVO.setNotFinish(groupByMonth(null));

        // 2、只统计当年一整年的数据
        Date beginTime = DateUtils.parseDate(year + "-01-01", "yyyy-MM-dd");
        Date endTime = DateUtils.parseDate(year + "-12-31", "yyyy-MM-dd");

        // 3、查询时间范围内的隐患排查记录
        final LambdaQueryWrapper<RiskMeasureTaskRecordEntity> wrapper = Wrappers.<RiskMeasureTaskRecordEntity>lambdaQuery()
                .ge(RiskMeasureTaskRecordEntity::getTaskStartTime, beginTime)
                .le(RiskMeasureTaskRecordEntity::getTaskStartTime, endTime);
        final List<RiskMeasureTaskRecordEntity> riskMeasureTaskRecordList = riskMeasureTaskRecordMapper.selectList(wrapper);
        if (CollectionUtil.isEmpty(riskMeasureTaskRecordList)) {
            return hiddenCheckStatusVO;
        }
        // 4、查询结果转Map
        final Map<Integer, List<RiskMeasureTaskRecordEntity>> listMap = riskMeasureTaskRecordList.parallelStream().filter(e ->
                ObjectUtil.isNotNull(e.getTaskStatus())).collect(Collectors.groupingBy(RiskMeasureTaskRecordEntity::getTaskStatus));

        hiddenCheckStatusVO.setExpire(groupByMonth(listMap.get(RiskDicConstant.HIDDEN_CHECK_TASK_STATUS_EXPIRE)));
        hiddenCheckStatusVO.setFinish(groupByMonth(listMap.get(RiskDicConstant.HIDDEN_CHECK_TASK_STATUS_FINISH)));
        hiddenCheckStatusVO.setNotFinish(groupByMonth(listMap.get(RiskDicConstant.HIDDEN_CHECK_TASK_STATUS_NOT_FINISH)));
        return hiddenCheckStatusVO;
    }

    @Override
    public RiskOperationalEvaluationEntity getOperationEvaluation() {
        final LambdaQueryWrapper<RiskOperationalEvaluationEntity> wrapper =
                Wrappers.<RiskOperationalEvaluationEntity>lambdaQuery().orderByDesc(RiskOperationalEvaluationEntity::getStartTime).last("limit 1");
        return Optional.ofNullable(riskOperationalEvaluationMapper.selectOne(wrapper)).orElseGet(() -> {
            final RiskOperationalEvaluationEntity entity = new RiskOperationalEvaluationEntity();
            entity.setNegatedItem(Boolean.FALSE);
            entity.setTotalPoints(BigDecimal.ZERO.doubleValue());
            entity.setHidTaskScore(BigDecimal.ZERO.doubleValue());
            entity.setRiskTaskScore(BigDecimal.ZERO.doubleValue());
            return entity;
        });
    }

    private Map<Integer, Integer> groupByMonth(List<RiskMeasureTaskRecordEntity> riskMeasureTaskRecordList) {
        Map<Integer, Integer> result = new HashMap<>();
        result.put(1, 0);
        result.put(2, 0);
        result.put(3, 0);
        result.put(4, 0);
        result.put(5, 0);
        result.put(6, 0);
        result.put(7, 0);
        result.put(8, 0);
        result.put(9, 0);
        result.put(10, 0);
        result.put(11, 0);
        result.put(12, 0);
        if (CollectionUtil.isNotEmpty(riskMeasureTaskRecordList)) {
            // 按照十二月份分组
            Map<Integer, List<RiskMeasureTaskRecordEntity>> groupByMonth = riskMeasureTaskRecordList.parallelStream().filter(e ->
                    ObjectUtil.isNotNull(e.getTaskStartTime())).collect(Collectors.groupingBy(it -> DateUtils.getMonth(it.getTaskStartTime())));
            groupByMonth.forEach((key, value) -> {
                result.put(key, value.size());
            });
        }
        return result;
    }
}
